;; supercollider/control.scm - (c) rohan drape, 2003-2005

;; A <control> represents a control in a UGen graph.  A <control> is
;; accessible by a <string> name, an <integer> index and is
;; implemented as an <output-proxy>.  The binary representation is a
;; 'Pascal String' followed by a signed two byte network order
;; integer.

(define-structure control (name 
			   index
			   value
			   lag
			   rate
			   proxy))

;; The control rate may be specified either as an <integer> or as a
;; <symbol>.  The normal form is an <integer>.

(define (control-rate-normal-form r)
  (if (integer? r) 
      r
      (case r
	((i init initialization) 0)
	((k ctl control) 1)
	((a audio) 2)
	(else (error "control-rate-normal-form: illegal rate value" r)))))

;;

(defineV (make-control name index value lag rate)
  (make-control* name index value lag (control-rate-normal-form rate) #f))

;; 

(define (control/proxy c proxy)
  (make-control* (control-name c)
		 (control-index c)
		 (control-value c)
		 (control-lag c)
		 (control-rate c)
		 proxy))

;; If `value' is a <list>, make a <list> of <control> values, else
;; defer to make-control.  The name of the first control is `name',
;; names for subsequent controls are of the form 'name_INDEX'.

(define (make-control/multiple name index value lag rate)
  (if (list? value)
      (map/index (lambda (n v)
		   (make-control 
		    (if (> n 0)
			(format "~a_~a" name n)
			name)
		    (+ index n)
		    v
		    lag 
		    rate))
		 value)
      (make-control name index value lag rate)))

(define (control-read port)
  (make-control (read-pascal-string port)
		(read-int16 port)
		#f 
		#f
		#f))

(define (control-write s port)
  (write-pascal-string (control-name s) port)
  (write-int16 (control-index s) port))

(define (control-encode s)
  (u8vector-append (encode-pascal-string (control-name s))
		   (encode-int16 (control-index s))))

;;

(define (control->input c)
  (output-proxy->input (control-proxy c)))
